#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import http.server
import socketserver
import socket
import webbrowser
import argparse
from pathlib import Path
import io
import mimetypes

def get_local_ip():
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            s.connect(("8.8.8.8", 80))
            return s.getsockname()[0]
    except Exception:
        return socket.gethostbyname(socket.gethostname())

class CustomHandler(http.server.SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        super().end_headers()

    def do_GET(self):
        # 解析当前路径
        current_path = Path(self.path.lstrip('/'))
        
        # 生成文件列表（如果不是根路径）
        file_list = []
        display_path = current_path  # 用于显示的路径
        
        # 如果请求的是目录（路径以斜杠结尾或为空）
        if self.path.endswith('/') or self.path == '/':
            try:
                # 如果不是根路径，获取实际目录
                if current_path != Path('.'):
                    current_dir = Path.cwd() / current_path
                else:
                    current_dir = Path.cwd()
                    
                display_path = current_dir  # 更新显示路径
                
                # 返回上层目录链接（根目录时不显示）
                parent_link = ""
                if self.path != '/':  # 不是根目录
                    parent_path = current_path.parent if current_path != Path('.') else Path('.')
                    parent_href = f'/{parent_path}/' if parent_path != Path('.') else '/'
                    parent_link = f'<a href="{parent_href}" style="color: #0066cc; margin-bottom: 15px; display: inline-block;">⬆ 返回上层目录</a>'
                
                # 添加目录项
                for item in current_dir.iterdir():
                    item_path = current_path / item.name
                    if not Path(item_path).exists():
                        print(f"!!! 无法访问目录: {item}")
                        continue
                    item_href = f'/{item_path}/' if item.is_dir() else f'/{item_path}'
                    
                    if item.is_dir():
                        file_list.append(f'<li><a href="{item_href}" style="color:blue;">📁 {item.name}/</a></li>')
                    else:
                        file_list.append(f'<li><a href="{item_href}" style="color:green;">📄 {item.name}</a> ({self._format_size(item.stat().st_size)})</li>')
                
                file_list_html = '\n'.join(file_list)
                
            except Exception as e:
                # 处理目录访问错误
                self.send_error(404, f"无法访问目录: {str(e)}")
                return
        else:
            # 如果请求的不是目录，使用默认处理
            super().do_GET()
            return
        
        # 构建HTML响应
        html = f'''
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>文件共享服务器 - {display_path}</title>
            <style>
                body {{ font-family: Arial, sans-serif; margin: 20px; }}
                h1 {{ color: #333; }}
                form {{ margin: 20px 0; padding: 15px; background-color: #f5f5f5; border-radius: 5px; }}
                ul {{ list-style-type: none; padding: 0; }}
                li {{ margin: 5px 0; }}
                a {{ text-decoration: none; }}
                a:hover {{ text-decoration: underline; }}
                .success-message {{ color: green; font-weight: bold; }}
                .error-message {{ color: red; }}
                /* 禁用按钮样式 */
                input[type="submit"]:disabled {{
                    background-color: #cccccc !important;
                    cursor: not-allowed !important;
                }}
            </style>
        </head>
        <body>
            <h1>当前目录: {display_path}</h1>
            
            
            <form action="/upload" method="post" enctype="multipart/form-data">
                <input type="file" name="file" id="fileInput" style="padding: 8px; border: 1px solid #ddd; border-radius: 4px;"
                    onchange="toggleUploadButton()" multiple>
                <input type="submit" value="上传文件" id="uploadButton" 
                    style="padding: 8px 15px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;"
                    disabled>
            </form>
            
            <h2>文件列表</h2>
            <ul>
                {parent_link}
                {file_list_html}
            </ul>
            
            <script>
                // 页面加载时检查文件输入状态
                document.addEventListener('DOMContentLoaded', function() {{
                    toggleUploadButton();
                }});
                
                // 切换上传按钮状态
                function toggleUploadButton() {{
                    const fileInput = document.getElementById('fileInput');
                    const uploadButton = document.getElementById('uploadButton');
                    uploadButton.disabled = !fileInput.value;
                }}
            </script>
        </body>
        </html>
        '''
        
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(html.encode('utf-8'))

    def do_POST(self):
        if self.path == '/upload':
            content_type = self.headers.get('Content-Type')
            if not content_type or not content_type.startswith('multipart/form-data'):
                self.send_error(400, 'Invalid Content-Type')
                return

            boundary = content_type.split('=')[1].encode()
            content_length = int(self.headers.get('Content-Length'))
            body = self.rfile.read(content_length)

            file_uploaded = False
            parts = body.split(boundary)
            for part in parts[1:-1]:
                part = part[2:-2]  # Remove leading and trailing CRLF
                if b'filename=' in part:
                    # Find the start of the file content
                    file_start = part.find(b'\r\n\r\n') + 4
                    file_content = part[file_start:]

                    # Extract the filename
                    filename_start = part.find(b'filename="') + 10
                    filename_end = part.find(b'"', filename_start)
                    filename = part[filename_start:filename_end].decode()

                    if filename:
                        # Save the file
                        upload_dir = Path.cwd() / 'upload'
                        upload_dir.mkdir(exist_ok=True)
                        file_path = upload_dir / filename
                        with open(file_path, 'wb') as f:
                            f.write(file_content)
                        file_uploaded = True

            if file_uploaded:
                # 返回成功消息并自动刷新页面
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                success_html = '''
                                <html>
                                <head><meta charset="utf-8"></head>
                                <body>
                                    <p class="success-message">文件上传成功!</p>
                                    <script>setTimeout(() => window.location = '/upload', 1000)</script>
                                </body>
                                </html>
                                '''
                self.wfile.write(success_html.encode('utf-8'))
            else:
                # 没有选择文件时的处理
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                error_html = '''
                            <html>
                            <head><meta charset="utf-8"></head>
                            <body>
                                <p style="color: red;">请选择要上传的文件!</p>
                                <script>setTimeout(() => window.history.back(), 1500)</script>
                            </body>
                            </html>
                            '''
                self.wfile.write(error_html.encode('utf-8'))
        else:
            super().do_POST()

    def _format_size(self, size_bytes):
        """将字节数转换为人类可读的格式"""
        units = ['B', 'KB', 'MB', 'GB', 'TB']
        unit_index = 0
        while size_bytes >= 1024 and unit_index < len(units) - 1:
            size_bytes /= 1024
            unit_index += 1
        return f"{size_bytes:.2f} {units[unit_index]}"

def main():
    parser = argparse.ArgumentParser(description="在局域网内共享当前目录的HTTP服务器")
    parser.add_argument("-p", "--port", type=int, default=8000, help="服务器端口号 (默认: 8000)")
    parser.add_argument("-o", "--open", action="store_true", help="在浏览器中打开本地页面")
    args = parser.parse_args()

    PORT = args.port
    current_dir = Path.cwd()
    local_ip = get_local_ip()

    Handler = CustomHandler

    print(f"服务器将在以下地址提供服务:")
    print(f"本地: http://localhost:{PORT}")
    print(f"局域网: http://{local_ip}:{PORT}")
    print(f"共享目录: {current_dir}")
    print("其他设备可以通过局域网地址访问这个服务器。")
    print("按 Ctrl+C 停止服务器。")

    if args.open:
        webbrowser.open(f"http://localhost:{PORT}")

    try:
        with socketserver.TCPServer(("", PORT), Handler) as httpd:
            httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n服务器已停止。")

if __name__ == "__main__":
    main()
